from PyQt4 import QtCore

#
# WList == Windowed List
#
# holds an array with a window - a width that is visble at any time
#
# also has a cursor indicating the current row
# which sounds like a violaton of the SRP to me
# But I can't see how separating that out would help, so ...
#
class WList(QtCore.QObject):
	changed = QtCore.pyqtSignal()

	def __init__(self, *args, **kw):
		QtCore.QObject.__init__(self)

		self.data = []		# the list
		self.width = 11		# the number of rows in the window
		self.base = 0		# the first row in the window
		self.curr_idx = 0	# the cursor position

#
#	getters and setters for the cursor
#
	@property
	def cursor(self):
		return self.curr_idx

#
#	we need to adjust the window if the cursor
#	moves outside. We also need to loop if we
#	hit the end or the start
#
	@cursor.setter
	def cursor(self, arg):
		value = 0

		if arg == None:
			return
#
#		allows us to pass a girl as well as an index
#		when setting the cursor
#
		if isinstance(arg, int):
			value = arg
		else:
			value = self.data.index(arg)
		llen = len(self.data)
#
#		check bounds - have we run off the end of the list?
#
		if value < 0:
			value = llen - 1
		elif value >= llen:
			value = 0
#
#		we can set the cursor, confident that we're
#		inside the list
#
		self.curr_idx = value
#
#		but we may need to scroll the widow to keep the
#		cursor inside the visible range
#
		if self.base > value:
			self.base = value
		elif value >= self.base + self.width: 
			self.base = value - self.width + 1
		self.changed.emit()

#
#	use slicing to return the sublist in the window
#
	@property
	def window(self):
		lo = self.base
		hi = lo + self.width
		return self.data[lo:hi+1]

#
#	current is the element under the cursor
#
	@property
	def current(self):
		return self.data[self.curr_idx]

#
#	forward a page
#
	def page(self):
		self.base += self.width
		if self.base >= len(self.data):
			self.base = 0
		self.changed.emit()

	def back(self):
		ln = len(self.data)
		if ln <= self.width:
			return
		self.base -= self.width
		if self.base < 0:
			self.base = len(self.data) - self.width
		self.curr_idx = self.base
		self.changed.emit()

	def sort(self, func, rev):
		self.data = sorted(self.data, key=func, reverse=rev)
		self.changed.emit()

	def getlist(self):
		return self.data

	def setlist(self, ll):
		self.curr_idx = 0
		self.data = ll
		self.changed.emit()

	list = property(getlist, setlist)


if __name__ == "__main__":

	wl = WList()
	wl.list = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
	print wl.window

	wl.page()
	print wl.window

	wl.page()
	print wl.window

	wl.page()
	print wl.window


	for i in range(20):
		wl.cursor += 1
		print wl.window

	print ""

	for i in range(20):
		wl.cursor -= 1
		print wl.window
